package mrusanov.ui.management

import javax.swing._
import javax.swing.event.{ListSelectionEvent, ListSelectionListener}
import mrusanov.team.{JuniorTeam, SecondTeam, FirstTeam, Team}
import mrusanov.player.Player
import table.{DefaultTableCellRenderer, DefaultTableModel}
import mrusanov.localization.Localization
import java.util.Date
import net.miginfocom.swing.MigLayout
import java.awt.datatransfer.{Transferable, DataFlavor}
import javax.activation.{DataHandler, ActivationDataFlavor}
import java.awt.dnd.DragSource
import java.awt._
import javax.swing.TransferHandler.TransferSupport
import collection.mutable.ArrayBuffer
import mrusanov.util.CollectionsUtil
import mrusanov.ui.player.PlayerSmallPanel
import scala.List
import mrusanov.ui.{PanelBuilder, CentralPanel}

class TeamRosterPanel(now:Date, team:Team) extends CentralPanel {
  private val columnsKeys = List("roster.table.status", "roster.table.name", "roster.table.playerType",
                             "roster.table.physicallyAtLevel","roster.table.level",
                             "roster.table.physical", "roster.table.age", "roster.table.talent",
                             "roster.table.salary", "roster.table.nationality")
  private val rightPanel = new JPanel()
  rightPanel.setLayout(new MigLayout("fill"))

  setLayout(new MigLayout("fill", null, "[top]"))
  private val rosterTable = new JTable()
  private val scrollPanel = new JScrollPane(rosterTable)
  add(scrollPanel, "grow, push")
  add(rightPanel, "width 300px")

  private val rosterTableModel = new DefaultTableModel() {
    override def isCellEditable(row:Int, column:Int) = false
  }

  columnsKeys foreach(key => rosterTableModel.addColumn(Localization(key)))
  team.roster foreach(pl => rosterTableModel.addRow(playerToRow(pl)))

  rosterTable.setModel(rosterTableModel)

  rosterTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION)
  rosterTable.getSelectionModel.addListSelectionListener(new ListSelectionListener {
    def valueChanged(e: ListSelectionEvent) {
      selectPlayer(rosterTable.getSelectionModel.getMinSelectionIndex)
    }
  })

  rosterTable.setCellSelectionEnabled(false)
  rosterTable.setRowSelectionAllowed(true)

  rosterTable.setDragEnabled(true)
  rosterTable.setDropMode(DropMode.INSERT_ROWS)
  rosterTable.setTransferHandler(new TableRowTransferHandler)
  rosterTable.setDefaultRenderer(classOf[Any], new TableCellRenderer)

  def playerToRow(player:Player):Array[AnyRef] = Array("", player.name, player.playerType.name, player.physicallyAtLevel.toString,
    player.level.toString, player.physicalShape.toString(), player.age(now).toString,
      player.talent.percentage.toString(), player.contract, player.nation.name)

  def reorderRows(from:Int, to:Int) {
    val data = rosterTableModel.getDataVector.get(from).asInstanceOf[java.util.Vector[Any]]
    rosterTableModel.removeRow(from)
    val correctedTo = if (from > to) to else to - 1
    rosterTableModel.insertRow(correctedTo, data)

    val moved = team.roster(from)
    val rosterWithRemovedPlayer = team.roster.filterNot(_ == moved)
    team.roster = CollectionsUtil.insertIntoVector(moved, rosterWithRemovedPlayer, correctedTo)
  }

  def selectPlayer(row:Int) {
    rightPanel.removeAll()
    val player = team.roster(row)
    val panel = new PlayerSmallPanel(player, now)
    rightPanel.add(panel)


    this.doLayout()
    this.validate()
  }

  override def buildItself(panelBuilder:PanelBuilder) = {
    team.teamLevel match {
      case FirstTeam => panelBuilder.firstTeam
      case SecondTeam => panelBuilder.secondTeam
      case JuniorTeam => panelBuilder.juniorTeam
    }
  }

  private class TableRowTransferHandler extends TransferHandler {
    private val localObjectFlavor = new ActivationDataFlavor(classOf[Int], DataFlavor.javaJVMLocalObjectMimeType, "Integer Row Index")
    private var rowFrom:Int =  -1

    override def createTransferable(c:JComponent):Transferable = {
      assert (c == rosterTable)
      rowFrom = rosterTable.getSelectedRow
      new DataHandler(None, localObjectFlavor.getMimeType)
    }

    override def canImport(info:TransferSupport):Boolean = {
      rosterTable.setCursor(DragSource.DefaultMoveDrop)
      true
    }

    override def getSourceActions(c:JComponent) = TransferHandler.COPY_OR_MOVE

    override def importData(info:TransferSupport):Boolean = {
      val dl = info.getDropLocation.asInstanceOf[JTable.DropLocation]
      val max = rosterTable.getModel.getRowCount
      val dlRow = dl.getRow
      val index = if (dlRow < 0 || dlRow > max) max else dlRow


      rosterTable.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR))

      if (rowFrom == -1 || rowFrom == index) {
        return false
      }

      reorderRows(rowFrom, index)
      val newSelectionIndex = if (index > rowFrom) index - 1 else index
      rosterTable.getSelectionModel.addSelectionInterval(newSelectionIndex, newSelectionIndex)
      true
    }


    override def exportDone(c:JComponent, t:Transferable, act:Int) {
      if (act == TransferHandler.MOVE) {
        rosterTable.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR))
      }
    }
  }

  private class TableCellRenderer extends DefaultTableCellRenderer {
    private val IN_GAME_COLOR = new Color(0, 127, 0)
    private val NOT_IN_GAME_COLOR = new Color(0, 0, 127)
    private val INJURED_COLOR = new Color(127, 0, 0)

    override def getTableCellRendererComponent(table:JTable, value:Any,
      isSelected:Boolean, hasFocus:Boolean, row:Int, column:Int):Component = {
        val component = super.getTableCellRendererComponent(table, value, isSelected, false, row, column)

        if (column != 0) {
          if (isSelected) {
            component.setBackground(table.getSelectionBackground)
          } else {
            component.setBackground(table.getBackground)
          }
          return component
        }

        val player = team.roster(row)

        val color = if (player.isInjured) {
          INJURED_COLOR
        } else if (team.playersForMatch.contains(player)){
          IN_GAME_COLOR
        } else {
          NOT_IN_GAME_COLOR
        }

        component.setBackground(color)
        component
      }
    }
}
